<template>
  <div class="employees-container">
    <div class="app-container">
      <page-tools>
        <template #left>
          <span>总记录数: {{ total }} 条</span>
        </template>
        <template #right>
          <el-button v-allow="'import_excel'" type="warning" size="small" @click="$router.push('/employees/import')">excel导入</el-button>
          <el-button v-allow="'export_excel'" type="danger" size="small" @click="hExport">excel导出</el-button>
          <el-button type="primary" size="small" @click="showDialog=true">新增员工</el-button>
        </template>
      </page-tools>

      <el-card style="margin-top: 10px;">
        <el-table border :data="employees">
          <el-table-column label="序号" type="index" />
          <el-table-column label="姓名" prop="username" />
          <el-table-column label="头像" width="80">
            <template v-slot="{row}">
              <img-holder :src="row.staffPhoto" />
            </template>
          </el-table-column>

          <el-table-column sortable label="工号" prop="workNumber" />
          <el-table-column label="聘用形式" prop="formOfEmployment">
            <template v-slot="{row}">
              {{ formatEmployees(row.formOfEmployment) }}
            </template>
          </el-table-column>

          <el-table-column label="部门" prop="departmentName" />
          <el-table-column sortable label="入职时间" prop="timeOfEntry" />
          <!-- <el-table-column label="账户状态" /> -->
          <el-table-column label="操作" width="280">
            <template v-slot="{row}">
              <!-- 查看对应的角色  传一个id过去 -->
              <el-button type="text" size="small" @click="$router.push('/employees/detail/' +row.id)">查看</el-button>
              <el-button type="text" size="small" @click="hAssignRole(row.id)">分配角色</el-button>
              <el-button type="text" size="small" @click="hDel(row.id)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <!-- 分页组件 -->
        <el-row type="flex" justify="center" align="middle" style="height: 60px">
          <el-pagination
            :current-page.sync="q.page"
            :page-size="q.size"
            :page-sizes="[10,15,20]"
            layout="total, sizes, prev, pager, next, jumper"
            :total="total"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
        </el-row>
      </el-card>
    </div>
    <el-dialog
      title="添加或编辑"
      :visible.sync="showDialog"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      @closed="$refs.addOrEdit.resetForm()"
    >
      <!-- 重置表单, 方案1: 给 addOrEdit组件 添加 v-if="showDialog" -->
      <addOrEdit ref="addOrEdit" @success="hSuccess" @close="hClose" />
    </el-dialog>

    <el-dialog
      title="分配角色"
      :visible.sync="showDialogRole"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <!-- 方案1: v-if -->
      <!-- <assignRole v-if="showDialogRole" :user-id="userId" @close="showDialogRole = false" /> -->
      <!-- 方案2: 子组件加一个ref, 直接在点击 分配角色时 调用子组件的方法 -->
      <assignRole ref="assignRole" :user-id="userId" @close="showDialogRole = false" />
    </el-dialog>
  </div>
</template>
<script>
import { delEmployee, getEmployeeList } from '@/api/employees'
import empConstant from '@/constant/employees' // 枚举数组对象
import addOrEdit from './empDialog'
import assignRole from './assignRole' // 分配角色 对话框 => 复选框
/*  hireType: [
    {
      id: 1,
      value: '正式'
    },
    {
      id: 2,
      value: '非正式'
    }
  ]
 */
//  将聘用形式的常量转成: { 1: '正式', 2: '非正式' }
// const obj = {}
// empConstant.hireType.forEach(item => { obj[item.id] = item.value })

// reduce 高级写法 ,属性名如果是变量, 需要用中括号包起来
const obj = empConstant.hireType.reduce((obj, item) => ({ ...obj, [item.id]: item.value }), {})
// console.log(obj)

export default {
  name: 'Employees',
  components: {
    addOrEdit, assignRole
  },
  data() {
    return {
      q: { // 请求参数
        page: 1,
        size: 10
      },
      total: 0, // 员工总数
      employees: [], // 员工信息列表
      showDialog: false, // 对话框显示隐藏
      showDialogRole: false, // 分配角色对话框
      userId: '' // 每个用户的id
    }
  },
  async created() { // 1. 只是页面加载 调用并渲染  2. 如果是导入Excel成功, 回退到此路由
    if (this.$route.query.state === 'success') { // 导入Excel成功后 ,自动跳转至最后一页
    // 编程式跳转, 传了个参数过来 , 判断一下
      const res = await getEmployeeList(this.q).catch(e => this.$message.error(e.message))
      this.total = res.data.total
      this.q.page = Math.ceil(this.total / this.q.size)
      this.loadEmployees()
    } else { this.loadEmployees() } // 页面加载, 就发请求 获取员工列表
  },
  methods: {
    async  loadEmployees() { // 获取员工列表 并渲染
      const res = await getEmployeeList(this.q).catch(e => this.$message.error(e.message))
      // console.log(res.data)
      this.employees = res.data.rows
      this.total = res.data.total
    },
    formatEmployees(code) { // 根据作用域插槽中的 状态码, 使用对象的中括号语法 确定返回值
      return obj[code]
    },
    handleSizeChange(val) { // 每页条数改变时,发请求
      console.log('每页显示条数:' + val)
      this.q.size = val
      this.loadEmployees()
    },
    handleCurrentChange(val) { // 当前页改变时,发请求
      console.log('当前页码:' + val)
      this.q.page = val
      this.loadEmployees()
    },
    async hDel(id) { // 删除员工
      // 确认框
      const result = await this.$confirm('确定要删除此员工吗?', '提示', { type: 'warning' }).catch(e => e)
      if (result !== 'confirm') return

      const res = await delEmployee(id).catch(e => this.$message.error(e.message))
      // 管理员不可删除 ,会进catch, 然后返回值 res 为$message组件 , 会继续走后面的代码
      // 做一个判断 , 只有删除成功才走后面代码
      if (!res.success) return

      this.$message.success(res.message)

      this.loadEmployees()
      //  处理分页问题,最后一页只有一个元素时
      if (this.employees.length === 1 && this.q.page > 1) this.q.page--
    },
    hClose() { // 子组件对话框点击 取消
      this.showDialog = false
    },
    async hSuccess() { // 新增成功后:  关闭对话框, 处理分页, 更新
      this.showDialog = false

      // 总数自增1 除以 每页条数 , 结果[向上取整] 赋值给当前页
      this.q.page = Math.ceil(++this.total / this.q.size)

      this.loadEmployees()
    },
    async hExport() { // Excel 导出
      const excel = await import('@/vendor/Export2Excel').catch(e => {})
      // excel表示导入的模块对象
      // console.log(excel) // Module模块
      // 身上有2个方法: export_json_to_excel  ;  export_table_to_excel

      // 发请求 拿员工的全部数据  ( page一页, size为员工总数total)
      const res = await getEmployeeList({ page: 1, size: this.total }).catch(e => e)
      // console.log(res)
      if (!res.success) { console.dir(res.message) }

      // 转换结构 (对结果进行解构)
      const { header, data } = this.format2Excel(res.data.rows)

      excel.export_json_to_excel({ // excel身上的 json转excel方法
        header, // 表头 必填  (直接使用解构后的header)  // ['姓名', '工资']
        data, // 具体数据 必填 (二维数组)               // [['刘备', 100],['关羽', 500]]
        filename: 'excel-list', // 文件名称
        autoWidth: true, // 宽度是否自适应
        bookType: 'xlsx' // 生成的文件类型
      })
    },
    format2Excel(list) { // ★ 数据转换 ★
      const mapInfo = {
        'id': '编号',
        'password': '密码',
        'mobile': '手机号',
        'username': '姓名',
        'timeOfEntry': '入职日期',
        'formOfEmployment': '聘用形式',
        'correctionTime': '转正日期',
        'workNumber': '工号',
        'departmentName': '部门',
        'staffPhoto': '头像地址'
      }
      let header = []
      let data = []
      // 如果传进来 空数组, 就 返回空对象(以免报错)
      if (!list.length) return { header, data }

      // 新增属性 , 会导致顺序错乱, 前端无法处理, 只能让后台给数据 设置默认值
      // 判断条件最好不要用 ! , 因为有可能 状态码是0
      list.forEach(item => {
        if (item.formOfEmployment === undefined) {
          item.formOfEmployment = '2'
        }
      })

      const enkeys = Object.keys(list[0]) // 对象属性较全的一项 的所有属性名 放入数组
      header = enkeys.map(k => mapInfo[k]) // 将英文 转成 中文属性名

      data = list.map(item => {
        const k = item.formOfEmployment // 1
        item.formOfEmployment = obj[k] // 正式 => 覆盖掉1   (obj 是全局枚举数组)

        const valuesArr = Object.values(item) // 取出每一项的 属性值 (因为导出需要 二维数组结构)
        const lastData = valuesArr[valuesArr.length - 1] // 拿到属性值数组 的最后一项 ,作判断

        // 判断条件不是很好
        if (lastData.indexOf('式') > 0) { // 因为是新增的聘用形式, 所以就放到最后面了, 所以需要换位置
          valuesArr.splice(5, 0, lastData) // 先用 splice 把最后一项 添加到指定位置
          valuesArr.pop() // 再把数组中最后一项删掉
        }

        return valuesArr // map返回 data 数组中 的每一项属性值数组
        // 不作判断的话, 直接返回 Object.values(item)就好了
      })

      // console.log(data, header)
      return { header, data }
    },
    async hAssignRole(id) { // 点击 分配角色 , 显示对话框
      this.userId = id
      // console.log(id)
      this.showDialogRole = true

      // 原因: props 的更新是异步的
      // (讲授写法: 两次请求分开发送的) 会出现 每一次的结果都是上一次的结果
      // (我的写法: 两次请求放在一个函数内) 会出现 无法获取 this.$refs.assignRole.loadRoles()

      // 加一个 nextTick 就好了
      await this.$nextTick()

      // 方案2: 调用子组件的方法让它发请求获取数据即可
      this.$refs.assignRole.loadRoles()
    }
  }
}
</script>
